<template>
    <view class="page over-auto-y column">
        <hj-navbar title="订单列表" />
        <OrderTab :orderStatus="params.orderStatus" @change="tabChange" />
        <!-- 内容区 -->
        <view class="flex-auto w100 over-hide">
            <scroll-view
                :scroll-y="true"
                class="big"
                :refresher-enabled="true"
                :refresher-triggered="triggered"
                @refresherrefresh="onRefresh"
                @scrolltolower="onScrollToLower"
            >
                <hj-loading :show="isInitLoad" v-if="isInitLoad" />
                <hj-no-data v-else-if="!orderList.length" tipsText="暂无订单数据~" />
                <block v-else>
                    <OrderList
                        :list="orderList"
                        @cancelOrder="cancelOrder"
                        @plyOrder="plyOrder"
                        @finishOrder="finishOrder"
                        @editOrder="editOrder"
                    />
                    <view
                        class="justify-content align-start"
                        style="height: 60rpx"
                        v-if="orderList.length > 0 && loadmoreShow"
                    >
                        <up-loadmore
                            :status="loadingStatus"
                            icon-type="flower"
                            fontSize="26rpx"
                            loadmoreText="上拉加载更多"
                            nomoreText="没有更多订单了~"
                        />
                    </view>
                </block>
            </scroll-view>
        </view>
        <!-- 底部安全区域 -->
        <hj-safe-footer />
        <!-- 取消原因选择弹窗 -->
        <CancelPopup v-model="showCancelPopup" :order="operateOrder" @cancelSubmit="cancelSubmit" />
        <!-- 修改弹窗 -->
        <EditPopup v-model="showEditPopup" :order="operateOrder" />
    </view>
</template>

<script setup>
/**
 * @description 订单列表
 * @author yinzhi
 * @date 2025-05
 */
import { onLoad, onShow, onUnload } from '@dcloudio/uni-app'
import { ref, defineComponent } from 'vue'
import { logger } from '@/utils/log.js'
import dayjs from 'dayjs/esm/index'
// 引入组件
import OrderTab from './components/OrderTab.vue'
import OrderList from './components/OrderList.vue'
import CancelPopup from './components/CancelPopup.vue'
import EditPopup from './components/EditPopup.vue'
import { getOrderApi, cancelUnPayApi, cancelPayApi, getPayOrderApi } from '@/libs/api/orderApi.js'
defineComponent({
    components: {
        OrderTab,
        OrderList,
        CancelPopup,
        EditPopup
    }
})
// 下拉刷新参数
const triggered = ref(false)
const _freshing = ref(false)
// 底部加载更多组件参数
const loadmoreShow = ref(false)
const loadingStatus = ref('loadmore') //loadmore nomore
// 取消原因弹窗显示
const showCancelPopup = ref(false)
// 修改弹窗
const showEditPopup = ref(false)
// 分页器参数
const params = ref({
    pageNo: 1,
    pageSize: 10,
    orderStatus: '' //订单状态 ''全部 1待付款 2待入住 入住中 4已完成
})
// 订单总数
const total = ref(0)
// 是否初始化加载
const isInitLoad = ref(true)
// 列表数据
const orderList = ref([])
// 正在操作的订单
const operateOrder = ref(null)
// 订单状态枚举
const orderStatusEnum = {
    1: 1,
    '2,3': 2,
    4: 3,
    '5,6,7': 4
}
onLoad(e => {
    // 从个人中心跳转的携带的参数 订单状态
    if (e.status) {
        params.value.orderStatus = orderStatusEnum[e.status] || ''
    }
    getOrderList()
})

// 每次页面加载
onShow(() => {
    // 先移除之前的监听器 防止重复监听 续订支付成功后返回页面需要更新订单列表
    uni.$off('initOrder')
    uni.$on('initOrder', data => {
        if (data.isInit) {
            pageInit()
        }
    })
    // 先移除之前的监听器 防止重复监听 监听订单详情页面取消倒计时结束后更新列表的状态，不更新接口
    uni.$off('upOrderList')
    uni.$on('upOrderList', data => {
        updateOrderList(data.orderNo)
    })
    // 修改订单后需要更新数据
    uni.$off('upDataOrder')
    uni.$on('upDataOrder', data => {
        updateOrderList(data.orderNo, data.isEdit)
    })
})
// 页面卸载
onUnload(() => {
    uni.$off('initOrder')
    uni.$off('upOrderList')
    uni.$off('upDataOrder')
})
// tab切换
const tabChange = status => {
    params.value.orderStatus = status
    isInitLoad.value = true
    pageInit()
}

// 初始化
const pageInit = () => {
    params.value.pageNo = 1
    orderList.value = []
    total.value = 0
    getOrderList()
}

// 付款倒计时结束自动取消订单
const finishOrder = async order => {
    const index = orderList.value.findIndex(item => item.orderNo === order.orderNo)
    if (index === -1) return
    orderList.value[index].orderStatus = 6
}

// 修改订单
const editOrder = order => {
    showEditPopup.value = true
    operateOrder.value = order
}

// 未付款取消
const cancelUnPay = async order => {
    try {
        await cancelUnPayApi({
            orderNo: order.orderNo
        })
        uni.showToast({
            title: '取消成功',
            icon: 'none',
            mask: true
        })
        await updateOrderList(order.orderNo)
    } catch (error) {
        logger.error('[cancelPayApi] 取消未支付订单失败:', error)
    }
}

// 取消订单规则 判断订单是否支付，未支付可以直接取消，其他状态需要打开取消原因选择弹窗
const cancelOrder = order => {
    if (order.orderStatus === 1) {
        uni.showModal({
            title: '取消订单',
            content: '确定取消当前订单吗？',
            success: res => {
                if (res.confirm) {
                    cancelUnPay(order)
                }
            }
        })
    } else {
        // 打开取消原因选择弹窗
        showCancelPopup.value = true
        operateOrder.value = order
    }
}
// 取消弹窗取消的订单
const cancelSubmit = async data => {
    try {
        await uni.showLoading({
            title: '加载中...'
        })
        const res = await cancelPayApi({
            orderNo: data.order?.orderNo || '',
            cancelReason: data.cancelReason
        })
        await updateOrderList(data.order?.orderNo)
        await uni.hideLoading()
        await uni.showToast({
            title: '提交成功',
            icon: 'none',
            mask: true
        })
    } catch (error) {
        await uni.hideLoading()
        logger.error('[cancelPayApi] 取消订单失败:', error)
    }
}

const requestPayment = data => {
    const orderNo = data.orderNo
    uni.requestPayment({
        timeStamp: data.timeStamp,
        nonceStr: data.nonceStr,
        package: data.packageValue,
        signType: data.signType,
        paySign: data.paySign,
        success: async res => {
            uni.showToast({
                title: '支付成功',
                icon: 'none',
                mask: true
            })
            await updateOrderList(orderNo)
        },
        fail: err => {
            uni.showToast({
                title: '取消支付',
                icon: 'none',
                mask: true
            })
        }
    })
}

// 支付订单
const plyOrder = async order => {
    try {
        const data = await getPayOrderApi({
            orderNo: order.orderNo,
            payBizType: 1, //1: 订单支付
            payWay: 1 //1: 微信支付
        })
        await requestPayment({
            ...data,
            orderNo: order.orderNo
        })
    } catch (error) {
        logger.error('[getPayOrderApi] 唤起支付失败: ', error)
    }
}

const orderStatusListEnum = {
    1: [1],
    2: [2, 3],
    3: [4],
    4: [5, 6, 7]
}
// 更新订单列表指定内容
const updateOrderList = async (orderNo, isEdit = false) => {
    uni.hideLoading()
    // 拿到orderNo在orderList.value中的角标
    const index = orderList.value.findIndex(item => item.orderNo === orderNo)
    if (index === -1) return
    const data = await getOrderApi({
        pageNo: index + 1,
        pageSize: 1,
        orderStatusList: orderStatusListEnum[params.value.orderStatus] || null
    })
    if (data.records.length > 0 && orderNo === data.records[0].orderNo) {
        const dataObj = {
            ...data.records[0],
            orderStatus:
                data.records[0].orderStatus === 1 &&
                Number(data.records[0].expectCancelTimeSeconds) <= 0
                    ? 6
                    : data.records[0].orderStatus
        }
        orderList.value.splice(index, 1, dataObj) // 更新订单列表指定内容
        if (isEdit) {
            operateOrder.value = dataObj
        }
    } else {
        orderList.value.splice(index, 1)
    }
}

// 获取订单列表
const getOrderList = async () => {
    try {
        const data = await getOrderApi({
            pageNo: params.value.pageNo,
            pageSize: params.value.pageSize,
            orderStatusList: orderStatusListEnum[params.value.orderStatus] || null
        })
        const list = [...orderList.value, ...data.records]
        orderList.value = list.map(item => {
            return {
                ...item,
                orderStatus:
                    item.orderStatus === 1 && Number(item.expectCancelTimeSeconds) <= 0
                        ? 6
                        : item.orderStatus
            }
        })
        total.value = data.total || 0
        loadmoreShow.value = total.value > 4 ? true : false
        loadingStatus.value = orderList.value.length === total.value ? 'nomore' : 'loadmore'
        // 关闭加载动画
        let time = setTimeout(() => {
            isInitLoad.value = false
            clearTimeout(time)
        }, 400)
    } catch (error) {
        isInitLoad.value = false
        loadingStatus.value = orderList.value.length === total.value ? 'nomore' : 'loadmore'
        logger.error('[getOrderList] 获取订单列表失败:', error)
    }
}

// 上拉加载更多
const onScrollToLower = () => {
    if (loadingStatus.value !== 'loading' && orderList.value.length < total.value) {
        params.value.pageNo += 1
        loadingStatus.value = 'loading'
        getOrderList()
    }
}

// 下拉刷新
const onRefresh = async () => {
    // 防止多次刷新
    if (_freshing.value) return
    _freshing.value = true
    triggered.value = true
    isInitLoad.value = true
    params.value.pageNo = 1
    getRefresh()
}
// 刷新事件 等所有接口请求 完成后使刷新动画回弹
const getRefresh = () => {
    Promise.all([pageInit()])
        .then(() => {
            let time = setTimeout(() => {
                triggered.value = false
                _freshing.value = false
                clearTimeout(time)
            }, 600)
        })
        .catch(() => {
            let time = setTimeout(() => {
                triggered.value = false
                _freshing.value = false
                clearTimeout(time)
            }, 600)
        })
}
</script>

<style scoped lang="scss">
.page {
    background: $uni-bg-color-grey;
}
:deep(.u-loadmore) {
    margin: 0 !important;
}
:deep(.u-count-down__text) {
    color: $uni-color-primary !important;
}
</style>
